﻿using System.Linq;
using Xenta.Entities;
using Xenta.Utils;

namespace Xenta.Operations
{
    #region __General__

    /// <summary>
    /// Creates a rating.
    /// </summary>
    /// <typeparam name="TRating">The type of rating.</typeparam>
    /// <typeparam name="TComment">The type of comment.</typeparam>
    public class CreateRating<TRating, TComment> : CreateAuditable<TRating>
        where TRating : RatingEntity
        where TComment : CommentEntity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the account identifier.
        /// </summary>
        public int HolderID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the account identifier.
        /// </summary>
        public int AccountID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the comment identifier.
        /// </summary>
        public int CommentID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the value.
        /// </summary>
        public byte Value
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Construct(IUnitOfWork uow, TRating entity)
        {
            base.Construct(uow, entity);

            entity.HolderID = HolderID;
            entity.Account = AccountID != 0 
                ? uow.Execute(new GetAccount
                {
                    ThrowsException = true,
                    EntityID = AccountID
                }).Result
                : null;
            entity.Comment = CommentID != 0
                ? uow.Execute(new GetComment<TComment>
                {
                    ThrowsException = true,
                    EntityID = CommentID
                }).Result
                : null;
            entity.Value = Value;
        }

        #endregion
    }

    /// <summary>
    /// Updates the rating.
    /// </summary>
    /// <typeparam name="TRating">The type of rating.</typeparam>
    public class UpdateRating<TRating> : UpdateAuditable<TRating>
        where TRating : RatingEntity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        public byte Value
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Revise(IUnitOfWork uow, TRating entity)
        {
            base.Revise(uow, entity);

            entity.Value = Value;
        }

        #endregion
    }

    /// <summary>
    /// Deletes the rating.
    /// </summary>
    /// <typeparam name="TRating">The type of rating.</typeparam>
    public class DeleteRating<TRating> : DeleteEntity<TRating>
        where TRating : RatingEntity
    {
    }

    /// <summary>
    /// Gets the rating by identifier.
    /// </summary>
    /// <typeparam name="TRating">The type of rating.</typeparam>
    public class GetRating<TRating> : GetEntity<TRating>
        where TRating : RatingEntity
    {
    }

    #endregion

    #region __Search__

    /// <summary>
    /// Search over rating collection.
    /// </summary>
    /// <typeparam name="TRating">The type of rating.</typeparam>
    public class SearchRatings<TRating> : SearchOperation<TRating>
        where TRating : RatingEntity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the holder identifier.
        /// </summary>
        public int? HolderID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the account identifier.
        /// </summary>
        public int? AccountID
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override IQueryable<TRating> Build(IUnitOfWork uow, IQueryable<TRating> query)
        {
            query = base.Build(uow, query);
            if(HolderID.HasValue)
                query = query.Where(x => x.HolderID == HolderID.Value);
            if(AccountID.HasValue)
                query = query.Where(x => x.Account.EntityID == AccountID.Value);
            return query;
        }

        #endregion
    }

    #endregion
}
